﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using Core.Helper;
using Core.Transmit;
using log4net;

namespace Core.Model.Transmit
{
    [DataContract]
    public  class TransmitDevice : INotifyPropertyChanged
    {
        private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public int Position { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string ChannelId { get; set; }

        //[DataMember]
        public string Protocol { get; set; }

        [DataMember]
        public bool IsWork { get; set; } = true;

        //[DataMember]
        public int Address { get; set; }
        //[DataMember]
        public ByteOrder ByteOrder { get; set; }

        private bool _isConnected = true;

        [DataMember]
        public bool IsConnected
        {
            get => _isConnected;
            set
            {
                if (value != _isConnected)
                {
                    _isConnected = value;
                    Global.DataAccess.PostData(Id, true, _isConnected);
                    try
                    {
                        if(_isConnected)
                            Global.DataAccess.AddEvent(EventType.Communication, EventLevel.Information, $"{Name}设备恢复连接!");
                        else
                           Global.DataAccess.AddEvent(EventType.Communication, EventLevel.Error, $"{Name}设备连接中断!");
                    }
                    catch
                    {
                    }
                    NotifyPropertyChanged("IsConnected");
                }
            }
        }


        public TransmitDevice()
        {
            Id = IdHelper.GuidToString();
            Name = "新设备";
            Address = 1;
        }

        public TransmitDevice Clone(string newId,string chlId)
        {
            TransmitDevice device = new TransmitDevice();
            device.Id = newId;
            device.Name = Name;
            device.Address = Address;
            device.ByteOrder = ByteOrder;
            device.ChannelId = chlId;
            device.Protocol = Protocol;
            device.Position = Position;
            return device;
        }
        public TransmitDeviceProtocol GetBaseDevProtocol()
        {
            try
            {
                if (!string.IsNullOrEmpty(this.Protocol))
                {
                    string strPath = Global.DataAccess.GetDevProtocolPath();
                    DirectoryInfo driverPath = new DirectoryInfo(strPath);
                    FileInfo[] files = driverPath.GetFiles();

                    for (int i = 0; i < files.Length; i++)
                    {
                        FileVersionInfo info = FileVersionInfo.GetVersionInfo(files[i].FullName);
                        if (info.ProductName != this.Protocol) continue;
                        if (files[i].Name.Contains(".dll") || files[i].Name.Contains(".DLL"))
                        {
                            string proPath = Path.Combine(strPath, files[i].Name);
                            Assembly asm = Assembly.Load(new AssemblyName() { CodeBase = proPath });
                            foreach (Type extype in asm.GetExportedTypes())
                            {
                                //确定type为类并且继承自(实现)BaseDevProtocol
                                if (extype.IsClass && typeof(TransmitDeviceProtocol).IsAssignableFrom(extype))
                                {
                                   return (TransmitDeviceProtocol)Activator.CreateInstance(extype);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                _log.Error(this.Protocol+"协议加载出错:" + e.Message);
            }
            return null;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
